package com.java.basis.thread.cas.atomic;

import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;

import java.util.ArrayList;
import java.util.List;

/**
 * @author wangning
 * @create 2022-01-29 15:40
 */
@Slf4j(topic = "c.Test07")
public class Test07 {
	public static void main(String[] args) {
		Account11.demo(new MyAtomicInteger(10000));


	}
}

class MyAtomicInteger implements Account11 {
	private volatile int value;
	private static final long valueOffset;
	private static final Unsafe UNSAFE;
	static {
		UNSAFE = UnsafeAccessor.getUnsafe();
		try {
			valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));

		} catch (NoSuchFieldException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	public int getValue() {
		return value;
	}

	public void decrement(int amount) {
		while (true) {
			int prev = this.value;
			int next = prev - amount;
			if (UNSAFE.compareAndSwapInt(this, valueOffset, prev, next)) {
				break;
			}
		}
	}

	public MyAtomicInteger(int value) {
		this.value = value;
	}

	@Override
	public Integer getBalance() {
		return getValue();
	}

	@Override
	public void withdraw(Integer amount) {
		decrement(amount);

	}
}

interface Account11 {
	//获取余额
	Integer getBalance();

	//取款
	void withdraw(Integer amount);

	/**
	 * 方法内启动1000个 线程，每个线程做-10元操作
	 * 如果初始余额为10000.那么正确的结果就是0
	 * @param account
	 */
	static void demo(Account11 account) {
		List<Thread> ts = new ArrayList<>();
		for (int i = 0; i < 1000; i++) {
			ts.add(new Thread(() -> {
				account.withdraw(10);
			}));
		}
		long start = System.nanoTime();
		ts.forEach(Thread::start);
		ts.forEach(t -> {
			try {
				t.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		long end = System.nanoTime();
		System.out.println(account.getBalance() + "元 cost: " + (end-start)/1000_000 + "ms");

	}
}
